import { ArcRotateCamera, BackgroundMaterial, Color3, Color4, CubeTexture, DirectionalLight, Engine, HemisphericLight, Mesh, MeshBuilder, MirrorTexture, Plane, Scene, ShadowGenerator, StandardMaterial, Texture, Texture, Vector3 } from "@babylonjs/core";

//镜面反射
export default class SkyBox {

    public engine: Engine;
    public scene: Scene;
    public canvas: HTMLCanvasElement;

    private updateAction: Map<number, (time: number) => {}> = new Map();
    private updateActionId: number = 0;

    public static skyBox: SkyBox;

    public constructor(canvas: HTMLCanvasElement) {
        this.canvas = canvas;
        this.engine = new Engine(canvas, true);
        this.scene = this.createScene();

        this.init();

        SkyBox.skyBox = this;
    }

    private init() {
        this.update(0);
    }

    private createScene() {
        const { engine, canvas } = this;
        let scene = new Scene(engine);
        scene.clearColor = new Color4(0, 0, 0, 1);

        const camera = new ArcRotateCamera('Camera', Math.PI / 2, Math.PI / 3, 10, new Vector3(0, 0, 0), scene);
        camera.attachControl(canvas, true);


        const matG = new BackgroundMaterial('backmat');
        matG.diffuseTexture = new Texture('../image/image01.png')
        matG.shadowLevel = 0.2;
        const ground = MeshBuilder.CreateGround('ground', { width: 5, height: 3 });
        // const ground = MeshBuilder.CreateSphere('ground', );
        ground.material = matG;
        ground.position.set(0, 1.49, 0);
        ground.rotation.set(-Math.PI / 2, Math.PI, 0);




        const mirror = new MirrorTexture('mirror', 1024, scene);
        mirror.mirrorPlane = new Plane(0, -1, 0, 0);
        mirror.renderList?.push(ground);
        const mat = new BackgroundMaterial('spheremat');
        mat.useRGBColor = false;
        mat.primaryColor = new Color3(0.1, 0.1, 0.1);
        mat.reflectionTexture = mirror;//反射纹理
        mat.reflectionFresnel = true;//开启反射菲涅尔

        const alphtTexture = new Texture('https://assets.babylonjs.com/environments/backgroundGround.png');
        alphtTexture.hasAlpha = true;
        mat.diffuseTexture = alphtTexture;//漫反射纹理

        mat.reflectionFresnel = true;//显示反射面颜色
        mat.reflectionStandardFresnelWeight = 0.9;//通透值?达到一种玻璃的效果

        const ground1 = MeshBuilder.CreateGround('ground', { width: 7, height: 5 });
        ground1.material = mat;


        //添加阴影
        const dir = new DirectionalLight('dir', new Vector3(-3, -3, -2), scene)
        ground1.receiveShadows = true;
        const shadowGen = new ShadowGenerator(512, dir);
        shadowGen.addShadowCaster(ground);
        mat.shadowLevel = 0.2;

        // //阴影模糊
        // shadowGen.useBlurExponentialShadowMap = true;
        // shadowGen.useKernelBlur = true;
        // shadowGen.blurKernel = 8;
        // shadowGen.blurScale = 5;
        // shadowGen.depthScale = 0;//???


        return scene;
    }

    private update(time: number) {
        const { updateAction, scene } = this;
        updateAction.forEach((action, key) => {
            action(time);
        });
        scene.render();
        requestAnimationFrame((time) => {
            this.update(time);
        });
    }

    public setUpdateAction(action: (time: number) => {}, id: number = -1) {
        const { updateAction } = this;
        let curId = id;
        if (id == -1) {
            curId = this.updateActionId++;
        } else if (id >= this.updateActionId) {
            curId = this.updateActionId++;
        }
        updateAction.set(curId, action);
    }
}